package hdgeom.primitives;

import processing.core.PGraphics;

public class Box{ 
	public float x1,y1,z1,x2,y2,z2;
	public Box(){
		x1=Float.POSITIVE_INFINITY;
		y1=Float.POSITIVE_INFINITY;
		z1=Float.POSITIVE_INFINITY;
		x2=Float.NEGATIVE_INFINITY;
		y2=Float.NEGATIVE_INFINITY;
		z2=Float.NEGATIVE_INFINITY;
	}
	public Box(float x1,float y1,float z1,float x2,float y2,float z2){
		this.x1=x1;
		this.y1=y1;
		this.z1=z1;
		this.x2=x2;
		this.y2=y2;
		this.z2=z2;
	}
	public Box(Box b){
		this.x1=b.x1;
		this.y1=b.y1;
		this.z1=b.z1;
		this.x2=b.x2;
		this.y2=b.y2;
		this.z2=b.z2;
	}
	public float getDimX(){
		return x2-x1;
	}
	public float getDimY(){
		return y2-y1;
	}
	public float getDimZ(){
		return z2-z1;
	}
	public float getCenterX(){
		return (x1+x2)*0.5f;
	}
	public float getCenterY(){
		return (y1+y2)*0.5f;
	}
	public float getCenterZ(){
		return (z1+z2)*0.5f;
	}
	public void display3D(PGraphics g3d){
		g3d.pushMatrix();
		g3d.translate(this.getCenterX(), this.getCenterY(),this.getCenterZ());
		g3d.box(this.getDimX(),this.getDimY(),this.getDimZ());
		g3d.popMatrix();
	}
	public void reOrient(){
		if (x1>x2){
			float tmp=x1;
			x1=x2;
			x2=tmp;
		}
		if (y1>y2){
			float tmp=y1;
			y1=y2;
			y2=tmp;
		}
		if (z1>z2){
			float tmp=z1;
			z1=z2;
			z2=tmp;
		}
	}
	public void add(Box box){
		this.x1=Math.min(box.x1, x1);
		this.y1=Math.min(box.y1, y1);
		this.z1=Math.min(box.z1, z1);
		this.x2=Math.max(box.x2, x2);
		this.y2=Math.max(box.y2, y2);
		this.z2=Math.max(box.z2, z2);
	}
	public void  intersect(Box box){
		
		this.x1=Math.max(box.x1, x1);
		this.y1=Math.max(box.y1, y1);
		this.z1=Math.max(box.z1, z1);
		this.x2=Math.min(box.x2, x2);
		this.y2=Math.min(box.y2, y2);
		this.z2=Math.min(box.z2, z2);
	}
	public void addPoint(float x,float y,float z){
		if (x<x1)x1=x;
		if (y<y1)y1=y;
		if (z<z1)z1=z;
		if (x>x2)x2=x;
		if (y>y2)y2=y;
		if (z>z2)z2=z;
	}
	public void scaleAroundCenter(float s){
		float cX=this.getCenterX();
		float cY=this.getCenterY();
		float cZ=this.getCenterZ();
		float dX=this.getDimX()*s*0.5f;
		float dY=this.getDimY()*s*0.5f;
		float dZ=this.getDimZ()*s*0.5f;
		this.x1=cX-dX;
		this.x2=cX+dX;
		this.y1=cY-dY;
		this.y2=cY+dY;
		this.z1=cZ-dZ;
		this.z2=cZ+dZ;
	}
	public void scale(float sx,float sy,float sz){
		this.x1*=sx;
		this.x2*=sx;
		this.y1*=sy;
		this.y2*=sy;
		this.z1*=sz;
		this.z2*=sz;
	}
	public void translate(float tx,float ty,float tz){
		this.x1+=tx;
		this.x2+=tx;
		this.y1+=ty;
		this.y2+=ty;
		this.z1+=tz;
		this.z2+=tz;
	}
	public float getMaxDimension(){
		return Math.max(Math.max(getDimX(), getDimY()), getDimZ());
	}

	
	public float getInnerDistance(float x,float y,float z){
		float minX=Math.min(Math.abs(x-x1),Math.abs(x-x2));
		float minY=Math.min(Math.abs(y-y1),Math.abs(y-y2));
		float minZ=Math.min(Math.abs(z-z1),Math.abs(z-z2));
		float minD=Math.min(minX, minY);
		minD=Math.min(minD, minZ);
		return minD;
	}

	public void offset(float offset){
		x1-=offset;
		y1-=offset;
		z1-=offset;
		x2+=offset;
		y2+=offset;
		z2+=offset;
	}
	public Box getOffsetBox(float offset){
		return new Box(x1-offset,y1-offset,z1-offset,x2+offset,y2+offset,z2+offset);
	}
	public float getOverlap(double a1,double a2,double b1,double b2){
		double v1=Math.max(a1, b1);
		double v2=Math.min(a2, b2);
		if (v2<v1)return 0;
		return (float)(v2-v1);
	}
	public float getOverlapVolume(Box r){
		float oY=getOverlap(r.y1,r.y2,y1,y2);
		if (oY<=0)return 0;
		float oX=getOverlap(r.x1,r.x2,x1,x2);
		if (oX<=0)return 0;
		float oZ=getOverlap(r.x1,r.z2,z1,z2);
		if (oZ<=0)return 0;
		return oX*oY*oZ;
	}
	public float getVolume(){
		return Math.abs(getDimX()*getDimY()*getDimZ());
	}
	public boolean isOverlap(float x1,float y1,float z1,float x2,float y2,float z2){
		float oY=getOverlap(y1,y2,this.y1,this.y2);
		if (oY<=0)return false;
		float oX=getOverlap(x1,x2,this.x1,this.x2);
		if (oX<=0)return false;
		float oZ=getOverlap(z1,z2,this.z1,this.z2);
		if (oZ<=0)return false;
		return true;
	}
	public boolean isOverlap(Box r){
		float oY=getOverlap(r.y1,r.y2,y1,y2);
		if (oY<0)return false;
		float oX=getOverlap(r.x1,r.x2,x1,x2);
		if (oX<0)return false;
		float oZ=getOverlap(r.z1,r.z2,z1,z2);
		if (oZ<0)return false;
		return true;
	}
	
	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "x1:"+x1+" y1:"+y1+" z1:"+z1+" dX:"+getDimX()+" dY:"+getDimY()+" dZ:"+getDimZ();
	}
	public boolean contains(float x,float y){
		if (x<x2&&x>=x1 && y<y2&&y>=y1 )return true;
		return false;
	}
	public boolean contains(float x,float y,float z){
		if (x<x2&&x>=x1 && y<y2&&y>=y1 && z<z2&&z>=z1)return true;
		return false;
	}
	
}
